﻿using System.Text;
using MTBrainStorm.Models.VirtualKeyboard;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MTBrainStorm.Models.VirtualKeyboard.VirtualKeyCodes;

namespace MTBrainStorm.Tests
{
	
	
	/// <summary>
	///This is a test class for VirtualKeyboardModelTest and is intended
	///to contain all VirtualKeyboardModelTest Unit Tests
	///</summary>
	[TestClass()]
	public class VirtualKeyboardModelTest
	{


		private TestContext testContextInstance;

		/// <summary>
		///Gets or sets the test context which provides
		///information about and functionality for the current test run.
		///</summary>
		public TestContext TestContext
		{
			get
			{
				return testContextInstance;
			}
			set
			{
				testContextInstance = value;
			}
		}

		private VirtualKeyboardModel _target;
		
		#region Additional test attributes
		// 
		//You can use the following additional attributes as you write your tests:
		//
		//Use ClassInitialize to run code before running the first test in the class
		//[ClassInitialize()]
		//public static void MyClassInitialize(TestContext testContext)
		//{
		//}
		//
		//Use ClassCleanup to run code after all tests in a class have run
		//[ClassCleanup()]
		//public static void MyClassCleanup()
		//{
		//}
		//
		//Use TestInitialize to run code before running each test
		[TestInitialize()]
		public void MyTestInitialize()
		{
			_target = new VirtualKeyboardModel();

			//load polish keyboard layout
			NativeMethods.LoadKeyboardLayout("00000415", 1);
		}
		//
		//Use TestCleanup to run code after each test has run
		//[TestCleanup()]
		//public void MyTestCleanup()
		//{
		//}
		//
		#endregion

		[TestMethod]
		public void GetCharacterTest()
		{
			var aLetter = _target.GetCharacter(Characters.A);
			Assert.AreEqual('a', aLetter);
		}

		[TestMethod]
		public void ShiftDownTest()
		{
			Assert.AreEqual(false, _target.IsShiftDown, "Shift should not be pressed");

			_target.ShiftDown();

			Assert.AreEqual(true, _target.IsShiftDown, "Shift should be pressed");
		}

		[TestMethod]
		public void ShiftUpTest()
		{
			Assert.IsFalse(_target.IsShiftDown, "Shift should not be pressed");

			_target.ShiftDown();
			Assert.IsTrue(_target.IsShiftDown, "Shift should be pressed.");

			_target.ShiftUp();
			Assert.IsFalse(_target.IsShiftDown, "Shift should not be pressed.");
		}

		[TestMethod]
		public void GetCharacterWithShiftTest()
		{
			var bLetter = _target.GetCharacter(Characters.B);
			Assert.AreEqual('b', bLetter, "Char should be lowercase");

			_target.ShiftDown();
			bLetter = _target.GetCharacter(Characters.B);
			Assert.AreEqual('B', bLetter, "Char should be uppercase");

			_target.ShiftUp();
			bLetter = _target.GetCharacter(Characters.B);
			Assert.AreEqual('b', bLetter, "Char should be lowercase");
		}

		[TestMethod]
		public void AltGrUpAndDownTest()
		{
			Assert.IsFalse(_target.IsAltGrDown, "AltGr should not be pressed");

			_target.AltGrDown();
			Assert.IsTrue(_target.IsAltGrDown, "AltGr should be pressed");

			_target.AltGrUp();
			Assert.IsFalse(_target.IsAltGrDown, "AltGr should not be pressed");
		}

		[TestMethod]
		public void GetCharacterWithAltGrTest()
		{
			Assert.IsFalse(_target.IsAltGrDown, "AltGr should not be pressed");

			Assert.AreEqual('a', _target.GetCharacter(Characters.A));

			_target.AltGrDown();
			Assert.AreEqual('ą', _target.GetCharacter(Characters.A));

			_target.AltGrUp();
			Assert.AreEqual('a', _target.GetCharacter(Characters.A));
		}

		[TestMethod]
		public void AllCharactersTest()
		{
			var expected =
				"``1234567890-=qwertyuiop[]\\asdfghjkl;'zxcvbnm,./~~!@#$%^&*()_+QWERTYUIOP{}|ASDFGHJKL:\"ZXCVBNM<>?";
			var builder = new StringBuilder();
			
			AppendAllChars(builder);
			_target.ShiftDown();
			AppendAllChars(builder);
			_target.ShiftUp();
			
			Assert.AreEqual(expected, builder.ToString());
		}

		private void AppendAllChars(StringBuilder builder)
		{
			builder.Append(_target.GetCharacter(Characters.Tilde));
			builder.Append(_target.GetCharacter(Characters.Tilde));
			builder.Append(_target.GetCharacter(Characters.N1));
			builder.Append(_target.GetCharacter(Characters.N2));
			builder.Append(_target.GetCharacter(Characters.N3));
			builder.Append(_target.GetCharacter(Characters.N4));
			builder.Append(_target.GetCharacter(Characters.N5));
			builder.Append(_target.GetCharacter(Characters.N6));
			builder.Append(_target.GetCharacter(Characters.N7));
			builder.Append(_target.GetCharacter(Characters.N8));
			builder.Append(_target.GetCharacter(Characters.N9));
			builder.Append(_target.GetCharacter(Characters.N0));
			builder.Append(_target.GetCharacter(Characters.Minus));
			builder.Append(_target.GetCharacter(Characters.Plus));
			builder.Append(_target.GetCharacter(Characters.Q));
			builder.Append(_target.GetCharacter(Characters.W));
			builder.Append(_target.GetCharacter(Characters.E));
			builder.Append(_target.GetCharacter(Characters.R));
			builder.Append(_target.GetCharacter(Characters.T));
			builder.Append(_target.GetCharacter(Characters.Y));
			builder.Append(_target.GetCharacter(Characters.U));
			builder.Append(_target.GetCharacter(Characters.I));
			builder.Append(_target.GetCharacter(Characters.O));
			builder.Append(_target.GetCharacter(Characters.P));
			builder.Append(_target.GetCharacter(Characters.LeftSquareBracket));
			builder.Append(_target.GetCharacter(Characters.RightSquareBracket));
			builder.Append(_target.GetCharacter(Characters.BackSlash));
			builder.Append(_target.GetCharacter(Characters.A));
			builder.Append(_target.GetCharacter(Characters.S));
			builder.Append(_target.GetCharacter(Characters.D));
			builder.Append(_target.GetCharacter(Characters.F));
			builder.Append(_target.GetCharacter(Characters.G));
			builder.Append(_target.GetCharacter(Characters.H));
			builder.Append(_target.GetCharacter(Characters.J));
			builder.Append(_target.GetCharacter(Characters.K));
			builder.Append(_target.GetCharacter(Characters.L));
			builder.Append(_target.GetCharacter(Characters.Semicolon));
			builder.Append(_target.GetCharacter(Characters.Apostrophe));
			builder.Append(_target.GetCharacter(Characters.Z));
			builder.Append(_target.GetCharacter(Characters.X));
			builder.Append(_target.GetCharacter(Characters.C));
			builder.Append(_target.GetCharacter(Characters.V));
			builder.Append(_target.GetCharacter(Characters.B));
			builder.Append(_target.GetCharacter(Characters.N));
			builder.Append(_target.GetCharacter(Characters.M));
			builder.Append(_target.GetCharacter(Characters.Comma));
			builder.Append(_target.GetCharacter(Characters.Dot));
			builder.Append(_target.GetCharacter(Characters.Slash));
		}

		[TestMethod]
		public void CapsLockToggleTest()
		{
			Assert.IsFalse(_target.IsCapsLockEnabled, "CapsLock should be disabled");
			Assert.AreEqual('g', _target.GetCharacter(Characters.G), "Char should be lowercase");

			_target.ToggleCapsLock();

			Assert.IsTrue(_target.IsCapsLockEnabled, "CapsLock should be enabled");
			Assert.AreEqual('D', _target.GetCharacter(Characters.D), "Char should be upper case");

			_target.ToggleCapsLock();

			Assert.IsFalse(_target.IsCapsLockEnabled, "CapsLock should be disabled");
			Assert.AreEqual('e', _target.GetCharacter(Characters.E), "Char should be lowercase");
		}
	}
}
